package utils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;

import javax.imageio.ImageIO;

public class MyUtil {
	public static int windowSizeForPeakSearching = 15;
	public static String[] seqStr = new String[] { "CTGAGTCGGAT",
			"TAGAGTCTGCC", "CTGAGTCGGTG", "CAGAGTCGAGG", "GCGAGTCGCTA",
			"TAGAGTCGTCA", "TCGAGTCGGAA", "GAGAGTCTATA", "ATGAGTCCCAA",
			"CAGAGTCGATT", "GTGAGTCCTTA", "ACGAGTCCATA", "TGGAGTCACAG",
			"GCGAGTCTTAT", "CTGAGTCCCTT" };
	public static double[] seqK = new double[] { 191.41, 277.91, 61.76, 99.56,
			3.08, 612.4, 53.2, 21987.17, 389.02, 739.65, 1532.11, 478.89,
			191.41, 666.12, 261.65 };

	public static String numberToGreeceString(int i) {
		switch (i) {
		case 1:
			return "\u03B1";
		case 2:
			return "\u03B2";
		case 3:
			return "\u03B3";
		case 4:
			return "\u03B4";
		case 5:
			return "\u03B5";
		case 6:
			return "\u03B6";
		case 7:
			return "\u03B7";
		case 8:
			return "\u03B8";
		case 9:
			return "\u03B9";
		case 10:
			return "\u03BA";
		default:
			return String.valueOf(i);
		}
	}

	public static String numberToString(int i) {
		switch (i) {
		case 1:
			return "a";
		case 2:
			return "b";
		case 3:
			return "c";
		case 4:
			return "d";
		case 5:
			return "e";
		case 6:
			return "f";
		case 7:
			return "g";
		case 8:
			return "h";
		case 9:
			return "i";
		case 10:
			return "j";
		default:
			return String.valueOf(i);
		}
	}

	public static void multiArrayCopy(double[][] source, double[][] destination) {
		for (int a = 0; a < source.length; a++) {
			System.arraycopy(source[a], 0, destination[a], 0, source[a].length);
		}
	}

	public static void multiArrayCopy(boolean[][] source,
			boolean[][] destination) {
		for (int a = 0; a < source.length; a++) {
			System.arraycopy(source[a], 0, destination[a], 0, source[a].length);
		}
	}

	public static void multiArrayCopy(boolean[][][] source,
			boolean[][][] destination) {
		for (int a = 0; a < source.length; a++) {
			boolean[][] tmp = source[a];
			for (int b = 0; b < tmp.length; b++) {
				System.arraycopy(source[a][b], 0, destination[a][b], 0,
						source[a][b].length);
			}
		}
	}

	public static void multiArrayCopy(double[][][] source,
			double[][][] destination) {
		for (int a = 0; a < source.length; a++) {
			double[][] tmp = source[a];
			for (int b = 0; b < tmp.length; b++) {
				System.arraycopy(source[a][b], 0, destination[a][b], 0,
						source[a][b].length);
			}
		}
	}

	public static double[] arrayListToDoulbe(List<Double> a) {
		int count = a.size();
		double[] result = new double[count];
		for (int i = 0; i < count; i++) {
			result[i] = (Double) a.get(i);
		}
		return result;
	}

	public static String doubleFormat(double value) {
		return String.format("%.4f", value);
	}

	public static double randomDouble(Random rand, double value1, double value2) {
		return value1 + rand.nextDouble() * (value2 - value1);
	}

	public static double randomDoubleLogScale(Random rand, double value1,
			double value2) {
		double log1 = Math.log(value1);
		double log2 = Math.log(value2);
		return Math.exp(randomDouble(rand, log1, log2));
	}

	public static double avgLogScale(double value1, double value2) {
		double log1 = Math.log(value1);
		double log2 = Math.log(value2);
		return Math.exp((log1 + log2) / 2);
	}

	public static int getFirstPeak(double[] data, int skipTime) {
		for (int i = skipTime + 1; i < data.length - 1; i++) {
			boolean peak = true;
			for (int j = Math.max(0, i - windowSizeForPeakSearching / 2); j < i; j++) {
				if (data[j] >= data[j + 1]) {
					peak = false;
					break;
				}
			}
			for (int j = i; j < Math.min(data.length - 1, i
					+ windowSizeForPeakSearching / 2); j++) {
				if (data[j] <= data[j + 1]) {
					peak = false;
					break;
				}
			}
			if (peak) {
				// System.out.println(i);
				return i;
			}
		}
		return -1;
	}

	public static int getFirstBottom(double[] data, int skipTime) {
		for (int i = skipTime + 1; i < data.length - 1; i++) {
			boolean peak = true;
			for (int j = Math.max(0, i - windowSizeForPeakSearching / 2); j < i; j++) {
				if (data[j] < data[j + 1]) {
					peak = false;
					break;
				}
			}
			for (int j = i; j < Math.min(data.length - 1, i
					+ windowSizeForPeakSearching / 2); j++) {
				if (data[j] > data[j + 1]) {
					peak = false;
					break;
				}
			}
			if (peak)
				return i;
		}
		return -1;
	}

	

	

	public static double distance(boolean[][][] matric1, boolean[][][] matric2) {
		int count = 0;
		int count2 = 0;
		for (int i = 0; i < matric1.length; i++) {
			for (int j = 0; j < matric1[i].length; j++) {
				for (int k = 0; k < matric1[i][j].length; k++) {
					if (matric1[i][j][k] != false || matric2[i][j][k] != false) {
						count++;
						if (matric1[i][j][k] != matric2[i][j][k]) {
							count2++;
						}
					}
				}
			}
		}
		System.out.println(count2 + "/" + count);
		return (double) count2 / count;
	}

	public static double calculateInhK(double K1, double K2) {
		return (double) 1 / 100 * Math.exp((Math.log(K1) + Math.log(K2)) / 2);
	}

	public static double getParamMutationFactor(double max, double min,
			double x, double r) {
		return Math.pow((max / min), r * x);
	}

	



	public static String getShortMutationString(String mutationString) {
		if (mutationString.contains("(-)")) {
			return "Switch";
		}
		if (mutationString.contains("Mutate Parameters")) {
			return "Parameter";
		}
		if (mutationString.contains("Mutate Add Activation")) {
			return "AddActivation";
		}
		if (mutationString.contains("Mutate Add Inhibition")) {
			return "AddInhibition";
		}
		if (mutationString.contains("Mutate Add Node")) {
			return "AddNode";
		}
		System.out.println(mutationString);
		return "?";
	}

	public static void createImage(Component component, String filepath,
			int width, int height) {

		BufferedImage bi = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_ARGB);
		Graphics g = bi.createGraphics();
		component.paint(g); // this == JComponent
		g.dispose();
		try {
			ImageIO.write(bi, "png", new File(filepath));
		} catch (Exception e) {
		}
	}



	public static double[] sampleEntropy(double[] y, int M, double r) {
		int n = y.length;
		int[] lastrun = new int[n];
		int[] run = new int[n];
		double[] A = new double[M];
		double[] B = new double[M];
		double[] p = new double[M];
		double[] e = new double[M];
		for (int i = 0; i < n - 1; i++) {
			int nj = n - i;
			double y1 = y[i];
			for (int jj = 0; jj < nj; jj++) {
				int j = jj + i;
				if (Math.abs(y[j] - y1) < r) {
					run[jj] = lastrun[jj] + 1;
					int M1 = Math.min(M, run[jj]);
					for (int m = 0; m < M1; m++) {
						A[m] = A[m] + 1;
						if (j < n) {
							B[m] = B[m] + 1;
						}
					}
				} else {
					run[jj] = 0;
				}
			}
			for (int j = 0; j < nj; j++) {
				lastrun[j] = run[j];
			}
		}
		int N = n * (n - 1) / 2;
		p[0] = A[0] / N;
		e[0] = -Math.log(p[0]);
		for (int m = 1; m < M; m++) {
			p[m] = A[m] / B[m - 1];
			e[m] = -Math.log(p[m]);
		}
		return e;
	}
}
